package com.gitee.wsl.concurrent.runnable

import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart.UNDISPATCHED
import kotlinx.coroutines.Job
import kotlinx.coroutines.Runnable
import kotlinx.coroutines.delay
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.launch

open class DelayedRunnable(
    val delayMillis: Int,
    private val scope: CoroutineScope,
    val runnable: Runnable
) : Runnable {
    var canceled = false
    var job: Job? = null

    override fun run() {
        if (canceled) return
        this.job = scope.launch(start = UNDISPATCHED) {
            delay(delayMillis.toLong())
            scope.ensureActive() // Necessary as delay() won't detect cancellation if the duration is 0.
            runnable.run()
        }
    }

    fun cancel() {
        canceled = true
        job?.cancel(CancellationException("only canceled"))
    }
}